#ifndef QOS_CPP_JOB
#define QOS_CPP_JOB

#include "task.hpp"
#include "list.hpp"
#include "logger.hpp"
#include "FSCP_Utils.hpp"
#include <cstdint>
#include <cstring>

namespace qOS {

    // Forward declaration of core class
    class core;

    /**
     * @brief Job state enumeration
     * @details Defines different running states of a Job
     */
    enum class JobState : uint8_t {
        CREATED,        /**< Job created but not initialized */
        INITIALIZED,    /**< Job initialized */
        RUNNING,        /**< Job is running */
        PAUSED,         /**< Job is paused */
        COMPLETED,      /**< Job completed */
        ERROR           /**< Job encountered an error */
    };

    /**
     * @brief Job execution mode
     * @details Defines the execution order of Tasks within a Job
     */
    enum class JobExecutionMode : uint8_t {
        SEQUENTIAL,     /**< Sequential execution: Tasks execute one after another */
        PARALLEL,       /**< Parallel execution: All Tasks execute simultaneously */
        PIPELINE,       /**< Pipeline execution: Tasks execute in pipeline fashion */
        CONDITIONAL     /**< Conditional execution: Execution path based on conditions */
    };

    /**
     * @brief Job dependency relationship
     * @details Defines dependency relationships between Tasks in a Job
     */
    struct JobDependency {
        size_t fromTaskId;      /**< Source Task ID that is depended on */
        size_t toTaskId;        /**< Target Task ID that has the dependency */
        uint32_t condition;     /**< Dependency condition */
        
        JobDependency();
        JobDependency(size_t from, size_t to, uint32_t cond = 0);
    };

    /**
     * @brief Job timing attributes structure
     * @details Defines timing constraints for Job scheduling
     */
    struct JobTimingAttr {
        uint64_t release_time;    /**< Earliest schedulable time (microseconds) */
        uint64_t deadline;        /**< Absolute deadline (microseconds) */
        uint64_t period;          /**< Period for periodic jobs (microseconds) */
        uint64_t wcet;            /**< Worst-case execution time (microseconds) */
        uint64_t jitter_bound;    /**< Maximum jitter bound (microseconds) */
        uint64_t slack;           /**< Dynamic slack time (microseconds) */
        
        JobTimingAttr();
        JobTimingAttr(uint64_t rel, uint64_t ddl, uint64_t per = 0, 
                      uint64_t wc = 0, uint64_t jit = 0, uint64_t slk = 0);
    };

    /**
     * @brief Job configuration structure
     * @details Defines Job configuration parameters
     */
    struct JobConfig {
        static const size_t MAX_NAME_LENGTH = 32;  /**< Maximum job name length */
        
        char name[MAX_NAME_LENGTH];               /**< Job name */
        JobExecutionMode executionMode;           /**< Execution mode */
        uint32_t timeout;                        /**< Job timeout (milliseconds) */
        uint32_t maxRetries;                      /**< Maximum retry count */
        bool autoStart;                          /**< Whether to auto-start */
        JobTimingAttr timingAttr;                 /**< Job timing attributes */
        
        JobConfig();
        JobConfig(const char *jobName, JobExecutionMode mode = JobExecutionMode::SEQUENTIAL, 
                  uint32_t to = 0, uint32_t retries = 0, bool start = false,
                  const JobTimingAttr& timing = JobTimingAttr());
    };

    /**
     * @brief Job statistics information
     * @details Records Job execution statistics
     */
    struct JobStatistics {
        uint32_t executionCount;        /**< Execution count */
        uint32_t successCount;          /**< Success count */
        uint32_t failureCount;          /**< Failure count */
        uint64_t totalExecutionTime;    /**< Total execution time (microseconds) */
        uint64_t lastExecutionTime;     /**< Last execution time (microseconds) */
        uint64_t startTime;             /**< Start time */
        
        JobStatistics();
    };

    // Output operator for JobStatistics
    inline logger::ChainLoggerProxy& operator<<(logger::ChainLoggerProxy& logger, const JobStatistics& stats) {
        logger << "[executions: " << stats.executionCount 
               << ", success: " << stats.successCount 
               << ", failure: " << stats.failureCount 
               << ", total_time: " << stats.totalExecutionTime << "us]";
        return logger;
    }

    /**
     * @brief Job class
     * @details Manages multiple Tasks as a Job object
     */
    class Job : private nonCopyable {
    private:
        static const size_t MAX_TASKS_PER_JOB = 16;  /**< Maximum tasks per job */
        
        JobConfig config;                   /**< Job configuration */
        JobState state;                     /**< Job state */
        JobStatistics stats;                /**< Statistics information */
        
        task *taskArray[MAX_TASKS_PER_JOB]; /**< Task array (pointers to tasks) */
        size_t taskCount;                   /**< Task count */
        
        list dependencyList;                /**< Dependency list */
        uint32_t currentRetryCount;         /**< Current retry count */
        
        bool taskCompletionFlags[MAX_TASKS_PER_JOB]; /**< Task completion flags */
        bool taskErrorFlags[MAX_TASKS_PER_JOB];     /**< Task error flags */
        
        uint64_t nextReleaseTime;           /**< Next release time for periodic jobs */
        uint64_t currentExecutionStart;     /**< Current execution start time */
        bool periodicEnabled;               /**< Whether periodic execution is enabled */
        
        // Pause/Resume mechanism
        uint64_t pauseTime;                 /**< Time when job was paused */
        uint64_t pausedExecutionTime;       /**< Execution time accumulated before pause */
        size_t currentTaskIndex;            /**< Current task index when paused */
        bool wasPeriodicBeforePause;        /**< Whether job was periodic before pause */
        uint64_t originalPeriod;             /**< Original period before pause */
        
        /**
         * @brief Check dependency relationships
         * @param taskIndex Task index
         * @return Whether dependency relationships are satisfied
         */
        bool checkDependencies(size_t taskIndex);

        /**
         * @brief Check if Job is completed
         * @return Whether Job is completed
         */
        bool isJobCompleted();

        /**
         * @brief Check if Job has failed
         * @return Whether Job has failed
         */
        bool isJobFailed();

        /**
         * @brief Complete the Job
         * @param success Whether completion was successful
         */
        void completeJob(bool success);

        /**
         * @brief Reset Job state
         */
        void resetJob();

        /**
         * @brief Check if job is ready to be scheduled
         * @param currentTime Current system time
         * @return Whether job is ready
         */
        bool isReady(uint64_t currentTime) const;

        /**
         * @brief Check if job deadline is missed
         * @param currentTime Current system time
         * @return Whether deadline is missed
         */
        bool isDeadlineMissed(uint64_t currentTime) const;

        /**
         * @brief Update dynamic slack time
         * @param currentTime Current system time
         * @return Updated slack time
         */
        uint64_t updateSlack(uint64_t currentTime);

        /**
         * @brief Save job state before pause
         */
        void savePauseState();

        /**
         * @brief Restore job state after resume
         */
        void restoreResumeState();

        /**
         * @brief Check if job can be paused
         * @return Whether job can be paused
         */
        bool canPause() const;

        /**
         * @brief Check if job can be resumed
         * @return Whether job can be resumed
         */
        bool canResume() const;

    public:
        /**
         * @brief Constructor
         * @param jobConfig Job configuration
         */
        Job(const JobConfig &jobConfig)
            : Job(jobConfig, 0)
        {}

        Job(const JobConfig &jobConfig, uint64_t securityToken);

        /**
         * @brief Destructor
         */
        ~Job();

        /**
         * @brief Add dependency relationship
         * @param dependency Dependency relationship
         * @return Whether addition was successful
         */
        bool addDependency(const JobDependency &dependency);

        /**
         * @brief Submit Job to scheduler (includes initialization)
         * @param os Operating system core
         * @param tasks Task array (optional - can be set later)
         * @param count Task count (optional - can be set later)
         * @param securityToken Security token for validation
         * @return Whether submission was successful
         */
        bool submit(core &os, task tasks[] = nullptr, size_t count = 0, uint64_t securityToken = 0ULL);

        /**
         * @brief Check if a specific task should execute now (for sequential mode)
         * @param taskPtr Pointer to task
         * @param securityToken Security token for validation
         * @return Whether task should execute
         */
        bool shouldExecuteTask(task* taskPtr, uint64_t securityToken);

        /**
         * @brief Get the execution mode of this job
         * @return Job execution mode
         */
        JobExecutionMode getExecutionMode() const;

        /**
         * @brief Get the security token of the job
         * @return Security token for functional safety verification
         */
        inline uint64_t GetSecurityToken(void) const noexcept
        {
            return m_securityToken;
        }

        /**
         * @brief Check timing constraints
         * @return Whether timing constraints are satisfied
         */
        bool checkTimingConstraints();

        /**
         * @brief Pause Job
         * @param securityToken Security token for validation
         */
        void pause(uint64_t securityToken = 0ULL);

        /**
         * @brief Resume Job
         * @param securityToken Security token for validation
         */
        void resume(uint64_t securityToken = 0ULL);

        /**
         * @brief Force pause Job (can be called from any state)
         * @param securityToken Security token for validation
         * @return Whether pause was successful
         */
        bool forcePause(uint64_t securityToken = 0ULL);

        /**
         * @brief Check if Job is paused
         * @return Whether job is paused
         */
        bool isPaused() const;

        /**
         * @brief Get pause duration
         * @return Duration in microseconds since pause
         */
        uint64_t getPauseDuration() const;

        /**
         * @brief Get Job state
         * @return Job state
         */
        JobState getState() const;

        /**
         * @brief Get Job statistics
         * @return Statistics information
         */
        JobStatistics getStatistics() const;

        /**
         * @brief Get Task count
         * @return Task count
         */
        size_t getTaskCount() const;

        /**
         * @brief Get Job timing attributes
         * @return Timing attributes
         */
        JobTimingAttr getTimingAttributes() const;

        /**
         * @brief Set Job timing attributes
         * @param timing Timing attributes
         * @return Whether setting was successful
         */
        bool setTimingAttributes(const JobTimingAttr& timing);

        /**
         * @brief Check if job is periodic
         * @return Whether job is periodic
         */
        bool isPeriodic() const;

        /**
         * @brief Get remaining slack time
         * @param currentTime Current system time
         * @return Remaining slack time in microseconds
         */
        uint64_t getRemainingSlack(uint64_t currentTime) const;

        /**
         * @brief Notify job that a task has started execution
         * @param taskIndex Index of the task that started
         * @param securityToken Security token for validation
         */
        void notifyTaskStarted(size_t taskIndex, uint64_t securityToken);

        /**
         * @brief Notify job that a task has completed execution
         * @param taskIndex Index of the task that completed
         * @param success Whether the task completed successfully
         * @param securityToken Security token for validation
         */
        void notifyTaskCompleted(size_t taskIndex, bool success = true, uint64_t securityToken = 0ULL);

        /**
         * @brief Notify job that a task has encountered an error
         * @param taskIndex Index of the task that encountered an error
         * @param errorCode Error code from the task
         * @param securityToken Security token for validation
         */
        void notifyTaskError(size_t taskIndex, uint32_t errorCode = 0, uint64_t securityToken = 0ULL);

        /**
         * @brief Get task pointer by index
         * @param taskIndex Task index
         * @param securityToken Security token for validation
         * @return Pointer to task, or nullptr if invalid index
         */
        task* getTask(size_t taskIndex, uint64_t securityToken) const;

        /**
         * @brief Find task index by task pointer
         * @param taskPtr Pointer to task
         * @param securityToken Security token for validation
         * @return Task index, or SIZE_MAX if not found
         */
        size_t findTaskIndex(const task* taskPtr, uint64_t securityToken) const;

        /**
         * @brief Check if all tasks are completed
         * @return Whether all tasks are completed
         */
        bool areAllTasksCompleted() const;

        /**
         * @brief Get job name
         * @return Job name
         */
        const char* getName() const;

        /**
         * @brief Check if any task has failed
         * @return Whether any task has failed
         */
        bool hasAnyTaskFailed() const;

        /**
         * @brief Clean up resources
         * @param securityToken Security token for validation
         */
        void cleanup(uint64_t securityToken = 0ULL);
    public:
        uint64_t m_securityToken;
    };

} // namespace qOS

#endif // QOS_CPP_JOB
